﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Mesuro.Equation.Libraries {
	//TODO: This should be made LibTeX and should include all TeX symbols
	public class LibTeX {
		public static readonly EqOperatorDefinition DegreeOperatorDefinition;
		public static readonly double DegFactor = 0.0174532925199433;//pi/180

		static LibTeX() {
			EqOperatorDefinition.Register( "\\", EqOperatorDefinition.PRECEDENCE_SYMBOL, EqOperatorArguments.PREFIX, GreekLookup );
			DegreeOperatorDefinition = EqOperatorDefinition.Register( "\u00B0", EqOperatorDefinition.PRECEDENCE_MULTIPLICATIVE, EqOperatorArguments.SINGLE, DegreeEval );
		}

		public static void Load() {
			try {
				//Try to ensure console output supports unicode characters
				Console.OutputEncoding = Encoding.GetEncoding( 65001 );
				//Console.InputEncoding = Encoding.GetEncoding( 65001 );//This doesn't work, Console doesn't support unicode input
			} catch (Exception) { }
		}

		public static EqTerm GreekLookup( EqScope scope, EqTerm LHS, EqTerm RHS, EqOperatorDefinition definition ) {

			if (!(RHS is EqSymbolInstance)) return null;//Can only handle symbol instances in this operator

			string name = ((EqSymbolInstance)RHS).Key;

			switch (name) {

				#region Greek
				#region Uppercase
				case "Alpha":
				case "ALPHA":
				case "A": return new EqSymbolInstance( "\u0391" ).Evaluate( scope );

				case "Beta":
				case "BETA":
				case "B": return new EqSymbolInstance( "\u0392" ).Evaluate( scope );

				case "Gamma":
				case "GAMMA":
				case "G": return new EqSymbolInstance( "\u0393" ).Evaluate( scope );

				case "Delta":
				case "DELTA":
				case "D": return new EqSymbolInstance( "\u0394" ).Evaluate( scope );

				case "Epsilon":
				case "EPSILON":
				case "E": return new EqSymbolInstance( "\u0395" ).Evaluate( scope );

				case "Zeta":
				case "ZETA":
				case "Z": return new EqSymbolInstance( "\u0396" ).Evaluate( scope );

				case "Eta":
				case "ETA":
				case "H": return new EqSymbolInstance( "\u0397" ).Evaluate( scope );

				case "Th":
				case "TH":
				case "U": return new EqSymbolInstance( "\u0398" ).Evaluate( scope );

				case "Iota":
				case "IOTA":
				case "I":
				case "J": return new EqSymbolInstance( "\u0399" ).Evaluate( scope );

				case "Kappa":
				case "KAPPA":
				case "K": return new EqSymbolInstance( "\u039A" ).Evaluate( scope );

				case "Lambda":
				case "LAMBDA":
				case "L": return new EqSymbolInstance( "\u039B" ).Evaluate( scope );

				case "Mu":
				case "MU":
				case "M": return new EqSymbolInstance( "\u039C" ).Evaluate( scope );

				case "Nu":
				case "NU":
				case "N": return new EqSymbolInstance( "\u039D" ).Evaluate( scope );

				case "Xi":
				case "XI":
				case "X": return new EqSymbolInstance( "\u039E" ).Evaluate( scope );

				case "Omicron":
				case "OMICRON":
				case "O": return new EqSymbolInstance( "\u039F" ).Evaluate( scope );

				case "Pi":
				case "PI":
				case "P": return new EqSymbolInstance( "\u03A0" ).Evaluate( scope );

				case "Rho":
				case "RHO":
				case "R": return new EqSymbolInstance( "\u03A1" ).Evaluate( scope );

				case "Sigma":
				case "SIGMA":
				case "S": return new EqSymbolInstance( "\u03A3" ).Evaluate( scope );

				case "Tau":
				case "TAU":
				case "T": return new EqSymbolInstance( "\u03A4" ).Evaluate( scope );

				case "Upsilon":
				case "UPSILON":
				case "Y": return new EqSymbolInstance( "\u03A5" ).Evaluate( scope );

				case "Phi":
				case "PHI":
				case "F": return new EqSymbolInstance( "\u03A6" ).Evaluate( scope );

				case "Chi":
				case "CHI":
				case "C": return new EqSymbolInstance( "\u03A7" ).Evaluate( scope );

				case "Psi":
				case "PSI":
				case "V": return new EqSymbolInstance( "\u03A8" ).Evaluate( scope );

				case "Omega":
				case "OMEGA":
				case "W": return new EqSymbolInstance( "\u03A9" ).Evaluate( scope );
				#endregion

				#region Lowercase
				case "alpha":
				case "a": return new EqSymbolInstance( "\u03B1" ).Evaluate( scope );

				case "beta":
				case "b": return new EqSymbolInstance( "\u03B2" ).Evaluate( scope );

				case "gamma":
				case "g": return new EqSymbolInstance( "\u03B3" ).Evaluate( scope );

				case "delta":
				case "d": return new EqSymbolInstance( "\u03B4" ).Evaluate( scope );

				case "epsilon":
				case "e": return new EqSymbolInstance( "\u03B5" ).Evaluate( scope );

				case "zeta":
				case "z": return new EqSymbolInstance( "\u03B6" ).Evaluate( scope );

				case "eta":
				case "h": return new EqSymbolInstance( "\u03B7" ).Evaluate( scope );

				case "th":
				case "u": return new EqSymbolInstance( "\u03B8" ).Evaluate( scope );

				case "iota":
				case "i":
				case "j": return new EqSymbolInstance( "\u03B9" ).Evaluate( scope );

				case "kappa":
				case "k": return new EqSymbolInstance( "\u03Ba" ).Evaluate( scope );

				case "lambda":
				case "l": return new EqSymbolInstance( "\u03Bb" ).Evaluate( scope );

				case "mu":
				case "m": return new EqSymbolInstance( "\u03Bc" ).Evaluate( scope );

				case "nu":
				case "n": return new EqSymbolInstance( "\u03Bd" ).Evaluate( scope );

				case "xi":
				case "x": return new EqSymbolInstance( "\u03Be" ).Evaluate( scope );

				case "omicron":
				case "o": return new EqSymbolInstance( "\u03Bf" ).Evaluate( scope );

				case "pi":
				case "p": return new EqSymbolInstance( "\u03C0" ).Evaluate( scope );

				case "rho":
				case "r": return new EqSymbolInstance( "\u03C1" ).Evaluate( scope );

				case "sigmax":
				case "sigmaFinal":
				case "sx": return new EqSymbolInstance( "\u03C2" ).Evaluate( scope );

				case "sigma":
				case "s": return new EqSymbolInstance( "\u03C3" ).Evaluate( scope );

				case "tau":
				case "t": return new EqSymbolInstance( "\u03C4" ).Evaluate( scope );

				case "upsilon":
				case "y": return new EqSymbolInstance( "\u03C5" ).Evaluate( scope );

				case "phi":
				case "f": return new EqSymbolInstance( "\u03C6" ).Evaluate( scope );

				case "chi":
				case "c": return new EqSymbolInstance( "\u03C7" ).Evaluate( scope );

				case "psi":
				case "v": return new EqSymbolInstance( "\u03C8" ).Evaluate( scope );

				case "omega":
				case "w": return new EqSymbolInstance( "\u03C9" ).Evaluate( scope );
				#endregion
				#endregion

				case "deg":
					return new EqOperatorInstance( DegreeOperatorDefinition );

				default: return null;//Not a known character identifier
			}
		}

		public static EqTerm DegreeEval( EqScope scope, EqTerm LHS, EqTerm RHS, EqOperatorDefinition definition ) {
			return new EqRealConstant( DegFactor );
		}
	}
}
